package com.iplant.wms.serviceImpl.dao.wms;

import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.CalendarTool;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.sql.BaseDAO;
import com.iplant.basic.service.basicenum.bfc.BFCMessageType;
import com.iplant.wms.service.basicenum.wms.WMSStockAlarmType;
import com.iplant.basic.service.po.bfc.BFCMessage;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.basic.service.po.bms.BMSRoleItem;
import com.iplant.wms.service.po.wms.WMSStock;
import com.iplant.wms.service.po.wms.WMSStockAlarm;
import com.iplant.wms.service.po.wms.WMSStockRecord;
import com.iplant.wms.service.po.wms.WMSStockSafe;
import com.iplant.basic.serviceImpl.dao.bfc.BFCMessageDAO;
import com.iplant.basic.serviceImpl.dao.bms.BMSRoleDAO;
import com.iplant.basic.utils.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.scheduling.annotation.Async;

import java.util.*;
import java.util.stream.Collectors;


public class WMSStockAlarmDAO extends BaseDAO implements DisposableBean {

    private static WMSStockAlarmDAO Instance = null;
    private static Logger logger = LoggerFactory.getLogger(WMSStockAlarmDAO.class);


    private WMSStockAlarmDAO() {
        super();

        setTableName("wms_stockalarm");
        AlarmEnable = Constants.StockAutoAlarmEnable == 1;
        if (AlarmEnable) {
            mThread = new Thread(() -> {
                this.WMS_StockThread(BMSEmployee.getSysAdmin());
            });
        }

    }

    public static WMSStockAlarmDAO getInstance() {
        if (Instance == null) {
            synchronized (WMSStockAlarmDAO.class) {
                if (Instance == null) {
                    Instance = new WMSStockAlarmDAO();
                }
            }
        }
        return Instance;
    }

    private Thread mThread;

    private static boolean AlarmEnable = false;

    public synchronized void WMS_UpdateStockAlarm(BMSEmployee wLoginUser, WMSStockAlarm wStockAlarm,
                                                  OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);

        try {
            if (wStockAlarm == null || StringUtils.isEmpty(wStockAlarm.Name)) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return;
            }
            WMSStockAlarm wStockAlarmO = this.WMS_CheckStockAlarm(wLoginUser, wStockAlarm, wErrorCode);
            if (wStockAlarmO.ID > 0) {
                wErrorCode.set(ExceptionTypes.Duplication.getValue());
            }
            if (wErrorCode.Result != 0) {
                return;
            }

            Map<String, Object> wParwms = new HashMap<String, Object>();

            wParwms.put("StoreID", wStockAlarm.StoreID);
            wParwms.put("StoreAreaID", wStockAlarm.StoreAreaID);
            wParwms.put("MaterialID", wStockAlarm.MaterialID);
            wParwms.put("BatchNo", wStockAlarm.BatchNo);
            wParwms.put("ProductDate", wStockAlarm.ProductDate);
            wParwms.put("StockDate", wStockAlarm.StockDate);
            wParwms.put("SafeDate", wStockAlarm.SafeDate);
            wParwms.put("SafeAlarmDate", wStockAlarm.SafeAlarmDate);
            wParwms.put("DeadDate", wStockAlarm.DeadDate);
            wParwms.put("MaxDeadDate", wStockAlarm.MaxDeadDate);
            wParwms.put("Type", wStockAlarm.Type);
            wParwms.put("AlarmNum", wStockAlarm.AlarmNum);
            wParwms.put("MinNum", wStockAlarm.MinNum);
            wParwms.put("MaxNum", wStockAlarm.MaxNum);
            wParwms.put("SafeNum", wStockAlarm.SafeNum);
            wParwms.put("Description", wStockAlarm.Description);

            wParwms.put("EditorID", wLoginUser.getID());
            wParwms.put("EditTime", Calendar.getInstance());

            if (wStockAlarm.ID > 0) {
                wParwms.put("ID", wStockAlarm.ID);
                super.Update(super.getTableName("wms_stockalarm"), "ID", wParwms);
            } else {

                if (StringUtils.isEmpty(wStockAlarm.Code)) {
                    wStockAlarm.Code = super.CreateMaxCode(super.getTableName("wms_stockalarm"),
                                                           StringUtils.Format("KCYJ-{0}-",
                                                                              StringUtils.parseCalendarToString(
                                                                                      Calendar.getInstance(), "yyMM")),
                                                           "Code", 4,wStockAlarm,0);
                }

                if (StringUtils.isEmpty(wStockAlarm.Description)) {
                    switch (WMSStockAlarmType.getEnumType(wStockAlarm.Type)) {

                        case SafeStock:
                            wStockAlarm.Description = StringUtils.Format("仓库({2})" +
                                                                                 (wStockAlarm.StoreAreaID > 0 ?
                                                                                         "库区({3})" :
                                                                                         "") + "中物料({0})库存({1}{4})低于安全库存",
                                                                         wStockAlarm.MaterialCode,
                                                                         wStockAlarm.AlarmNum, wStockAlarm.StoreName,
                                                                         wStockAlarm.StoreAreaName,
                                                                         wStockAlarm.UnitText);
                            break;
                        case LimitStock:
                            if (wStockAlarm.MaxNum > 0 && wStockAlarm.MaxNum <= wStockAlarm.AlarmNum) {
                                wStockAlarm.Description = StringUtils.Format("仓库({2})" +
                                                                                     (wStockAlarm.StoreAreaID > 0 ?
                                                                                             "库区({3})" :
                                                                                             "") + "中物料({0})库存({1}{4})超出或低于库存限制",
                                                                             wStockAlarm.MaterialCode,
                                                                             wStockAlarm.AlarmNum,
                                                                             wStockAlarm.StoreName,
                                                                             wStockAlarm.StoreAreaName,
                                                                             wStockAlarm.UnitText);
                            } else if (wStockAlarm.MinNum > 0 && wStockAlarm.MinNum >= wStockAlarm.AlarmNum) {
                                wStockAlarm.Description = StringUtils.Format("仓库({2})" +
                                                                                     (wStockAlarm.StoreAreaID > 0 ?
                                                                                             "库区({3})" :
                                                                                             "") + "中物料({0})库存({1}{4})超出或低于库存限制",
                                                                             wStockAlarm.MaterialCode,
                                                                             wStockAlarm.AlarmNum,
                                                                             wStockAlarm.StoreName,
                                                                             wStockAlarm.StoreAreaName,
                                                                             wStockAlarm.UnitText);
                            } else {
                                return;
                            }

                            break;
                        case SafeDate:
                            if (wStockAlarm.getOverDueSafe() < 0) {
                                wStockAlarm.Description =
                                        StringUtils.Format("仓库({2})库区({3})中批次为{4}的物料({0})还剩{1}天超过质保期，请尽快使用！",
                                                           wStockAlarm.MaterialCode,
                                                           -wStockAlarm.getOverDueSafe(), wStockAlarm.StoreName,
                                                           wStockAlarm.StoreAreaName, wStockAlarm.BatchNo);
                            } else {
                                wStockAlarm.Description =
                                        StringUtils.Format("仓库({2})库区({3})中批次为{4}的物料({0})已经超出保质期{1}天，请尽块处理！",
                                                           wStockAlarm.MaterialCode,
                                                           wStockAlarm.getOverDueSafe(), wStockAlarm.StoreName,
                                                           wStockAlarm.StoreAreaName, wStockAlarm.BatchNo);
                            }

                            break;
                        case DeadDate:
                            wStockAlarm.Description =
                                    StringUtils.Format("仓库({2})库区({3})中批次为{4}的物料({0})，入库日期为{1}，已判定为呆滞物料，请尽快处理！",
                                                       wStockAlarm.MaterialCode,
                                                       StringUtils.CalendarFormat(wStockAlarm.StockDate, "yyyy-MM-dd"),
                                                       wStockAlarm.StoreName, wStockAlarm.StoreAreaName,
                                                       wStockAlarm.BatchNo);
                            break;
                        case MaxDeadDate:
                            wStockAlarm.Description =
                                    StringUtils.Format("仓库({2})库区({3})中批次为{4}的物料({0})，入库日期为{1}，已超出最大存储期限，请尽快处理！",
                                                       wStockAlarm.MaterialCode,
                                                       StringUtils.CalendarFormat(wStockAlarm.StockDate, "yyyy-MM-dd"),
                                                       wStockAlarm.StoreName, wStockAlarm.StoreAreaName,
                                                       wStockAlarm.BatchNo);
                            break;
                        case Default:
                        default:
                            return;
                    }

                }


                wParwms.put("Code", wStockAlarm.Code);
                wParwms.put("Active", 1);
                wParwms.put("CreatorID", wLoginUser.getID());
                wParwms.put("CreateTime", Calendar.getInstance());
                wStockAlarm.ID = super.Insert(super.getTableName("wms_stockalarm"), wParwms);

                // 生成通知消息并提示

                BFCMessage wBFCMessage = new BFCMessage();

                wBFCMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessage.CompanyID = wLoginUser.CompanyID;
                wBFCMessage.MessageID = wStockAlarm.ID;

                wBFCMessage.MessageText = wStockAlarm.Description;

                wBFCMessage.ModuleID = 0;
                wBFCMessage.ShiftID = CalendarTool.getShiftID(Calendar.getInstance());
                wBFCMessage.Title = "库存预警";
                List<BMSRoleItem> wBMSRoleItemList = BMSRoleDAO.getInstance().BMS_QueryUserListByFunctionID(wLoginUser,
                                                                                                            111,
                                                                                                            wErrorCode);

                if (wBMSRoleItemList == null || wBMSRoleItemList.size() <= 0) {
                    return;
                }
                Map<Integer, String> wUserDic = wBMSRoleItemList.stream()
                        .collect(Collectors.toMap(p -> p.UserID, p -> p.Text));

                BFCMessageDAO.getInstance().BFC_InsertMessage(wLoginUser, wBFCMessage, wUserDic, wErrorCode);
            }

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("WMS_UpdateStockAlarm", ex);
        }
    }

    public void WMS_ActiveStockAlarm(BMSEmployee wLoginUser, WMSStockAlarm wStockAlarm, int wActive,
                                     OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        // 判断客户信息是否存在(中国：统一社会信用代码，国外:提醒是否有重复）

        try {
            if (wStockAlarm == null || wStockAlarm.ID <= 0) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return;
            }

            Map<String, Object> wParwms = new HashMap<String, Object>();

            wParwms.put("ID", wStockAlarm.ID);
            wParwms.put("EditorID", wLoginUser.getID());
            wParwms.put("EditTime", Calendar.getInstance());
            wParwms.put("Active", wActive);
            super.Update(super.getTableName("wms_stockalarm"), "ID", wParwms);

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());

            logger.error("WMS_ActiveStockAlarm", ex);
        }
    }

    public List<WMSStockAlarm> WMS_QueryStockAlarmList(BMSEmployee wLoginUser, int wFactoryID, int wStoreRegionID,
                                                       int wStoreID, String wStoreCode, String wStoreName,
                                                       int wStoreAreaID, String wStoreAreaCode,
                                                       String wStoreAreaName, int wMaterialID, String wMaterialCode,
                                                       String wMaterialName, String wName,
                                                       int wActive, Calendar wStartTime, Calendar wEndTime,
                                                       Pagination wPagination, OutResult<Integer> wErrorCode) {
        return this.WMS_QueryStockAlarmList(wLoginUser, -1, "", wFactoryID, wStoreRegionID, wStoreID, wStoreCode,
                                            wStoreName, wStoreAreaID, wStoreAreaCode, wStoreAreaName, wMaterialID,
                                            wMaterialCode, wMaterialName,
                                            wName, wActive, wStartTime, wEndTime, wPagination, wErrorCode);
    }

    private List<WMSStockAlarm> WMS_QueryStockAlarmList(BMSEmployee wLoginUser, int wID, String wCode, int wFactoryID,
                                                        int wStoreRegionID, int wStoreID, String wStoreCode,
                                                        String wStoreName, int wStoreAreaID,
                                                        String wStoreAreaCode, String wStoreAreaName, int wMaterialID,
                                                        String wMaterialCode, String wMaterialName,
                                                        String wName, int wActive, Calendar wStartTime,
                                                        Calendar wEndTime, Pagination wPagination,
                                                        OutResult<Integer> wErrorCode) {
        List<WMSStockAlarm> wWMSStockAlarmList = new ArrayList<WMSStockAlarm>();
        wErrorCode.set(0);

        try {

            Calendar wBaseTime = CalendarTool.getCalendar(2000, 1, 1);
            if (wStartTime.compareTo(wBaseTime) < 0) {
                wStartTime = wBaseTime;
            }
            if (wEndTime.compareTo(wBaseTime) < 0) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) > 0) {
                return wWMSStockAlarmList;
            }

            // Step02:查询
            Map<String, Object> wParwms = new HashMap<String, Object>();
            String wSQLText = "";
            wSQLText = StringUtils.Format("Select t.*,t1.Name as StoreName,t1.Code as StoreCode,t1.FactoryID,"
                                                  + " t1.StoreRegionID,t5.Name as FactoryName,t5.Code as FactoryCode,t8.Name as StoreAreaName,t8.Code as StoreAreaCode,"
                                                  + " t2.Name as StoreRegionName,t2.Code as StoreRegionCode,t6.MaterialName,"
                                                  + " t6.Code as MaterialCode,t6.CYUnitID as UnitID, t7.Code as UnitCode,t7.Name as UnitText, "
                                                  + " t3.Name as CreatorName ,t4.Name as EditorName  from {0}.wms_stockalarm t  "
                                                  + " left join {0}.wms_store t1 on t.StoreID=t1.ID "
                                                  + " left join {0}.wms_storearea t8 on t.StoreAreaID=t8.ID "
                                                  + " left join {0}.fmc_factory t5 on t1.FactoryID=t5.ID "
                                                  + " left join {0}.wms_storeregion t2 on t1.StoreRegionID=t2.ID "
                                                  + " left join {0}.mbs_user t3 on t.CreatorID=t3.ID "
                                                  + " left join {0}.mbs_user t4 on t.EditorID=t4.ID "
                                                  + " left join {0}.mss_material t6 on t.MaterialID=t6.ID "
                                                  + " left join {0}.mss_unit t7 on t6.CYUnitID=t7.ID "
                                                  + " where (:ID<=0 or  t.ID=:ID) and (:Code =''''  or  t.Code=:Code)"
                                                  + " AND (:FactoryID<=0 or  t1.FactoryID=:FactoryID) "
                                                  + " AND (:StoreRegionID<=0 or  t1.StoreRegionID=:StoreRegionID) AND (:StoreID<=0 or  t.StoreID=:StoreID)  "
                                                  + " AND (:StoreAreaID<0 or  t.StoreAreaID=:StoreAreaID) AND (:MaterialID<=0 or  t.MaterialID=:MaterialID)"
                                                  + " AND (:Active<0 or  t.Active=:Active) and (:MaterialCode =''''  or  t6.Code=:MaterialCode)"
                                                  + " AND (:MaterialName = '''' or  t6.Name like :MaterialName) "
                                                  + " AND (:StoreName = '''' or  t1.Name like :StoreName) "
                                                  + " AND (:StoreCode = '''' or  t1.Code like :StoreCode) "
                                                  + " AND (:StoreAreaName = '''' or  t8.Name like :StoreAreaName) "
                                                  + " AND (:StoreAreaCode = '''' or  t8.Code like :StoreAreaCode) "
                                                  + " AND ( :StartTime <=str_to_date(''2010-01-01'', ''%Y-%m-%d'')  or :StartTime <=  t.CreateTime )"
                                                  + " AND ( :EndTime <=str_to_date(''2010-01-01'', ''%Y-%m-%d'')  or :EndTime >=  t.CreateTime ) "
                    , super.getDBName());

            wSQLText = this.DMLChange(wSQLText);

            wParwms.put("ID", wID);
            wParwms.put("Code", wCode);
            wParwms.put("FactoryID", wFactoryID);
            wParwms.put("StoreRegionID", wStoreRegionID);
            wParwms.put("StoreID", wStoreID);
            wParwms.put("StoreName", StringUtils.isEmpty(wStoreName) ? "" : ("%" + wStoreName + "%"));
            wParwms.put("StoreCode", StringUtils.isEmpty(wStoreCode) ? "" : ("%" + wStoreCode + "%"));
            wParwms.put("StoreAreaID", wStoreAreaID);
            wParwms.put("StoreAreaName", StringUtils.isEmpty(wStoreAreaName) ? "" : ("%" + wStoreAreaName + "%"));
            wParwms.put("StoreAreaCode", StringUtils.isEmpty(wStoreAreaCode) ? "" : ("%" + wStoreAreaCode + "%"));
            wParwms.put("MaterialID", wMaterialID);
            wParwms.put("MaterialCode", wMaterialCode);
            wParwms.put("MaterialName", StringUtils.isEmpty(wMaterialName) ? "" : ("%" + wMaterialName + "%"));
            wParwms.put("Active", wActive);

            wParwms.put("StartTime", wStartTime);
            wParwms.put("EndTime", wEndTime);
            wWMSStockAlarmList = super.QueryForList(wSQLText, wParwms, wPagination, WMSStockAlarm.class);

            // Step03:配置系统
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("WMS_QueryStockAlarmList", ex);
        }
        return wWMSStockAlarmList;
    }

    public WMSStockAlarm WMS_QueryStockAlarm(BMSEmployee wLoginUser, int wID, String wCode,
                                             OutResult<Integer> wErrorCode) {
        WMSStockAlarm wResult = new WMSStockAlarm();
        wErrorCode.set(0);

        try {
            List<WMSStockAlarm> wList = null;
            if (wID > 0) {
                wList = this.WMS_QueryStockAlarmList(wLoginUser, wID, "", -1, -1, -1, "", "", -1, "", "", -1, "", "",
                                                     "", -1, CalendarTool.getBasicDate(), CalendarTool.getBasicDate(),
                                                     Pagination.getDefault(), wErrorCode);

            } else if (StringUtils.isNotEmpty(wCode)) {
                wList = this.WMS_QueryStockAlarmList(wLoginUser, -1, wCode, -1, -1, -1, "", "", -1, "", "", -1, "", "",
                                                     "", -1, CalendarTool.getBasicDate(), CalendarTool.getBasicDate(),
                                                     Pagination.getDefault(), wErrorCode);
            }
            if (wList != null && wList.size() > 0) {
                wResult = wList.get(0);
            }
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("WMS_QueryStockAlarmByID", ex);
        }
        return wResult;
    }

    public WMSStockAlarm WMS_CheckStockAlarm(BMSEmployee wLoginUser, WMSStockAlarm wWMSStockAlarm,
                                             OutResult<Integer> wErrorCode) {
        WMSStockAlarm wStockAlarm = new WMSStockAlarm();
        wErrorCode.set(0);

        try {

            // Step0:查询
            Map<String, Object> wParwms = new HashMap<String, Object>();
            String wSQLText = StringUtils.Format("Select * from {0}.wms_stockalarm "
                                                         + " where ID!=:ID and ( (StoreID=:StoreID AND MaterialID =:MaterialID AND Active=1) or (:Code != '''' and Code=:Code)) ",
                                                 super.getDBName());
            wParwms.clear();
            wParwms.put("ID", wWMSStockAlarm.ID);
            wParwms.put("MaterialID", wWMSStockAlarm.MaterialID);
            wParwms.put("StoreID", wWMSStockAlarm.StoreID);
            wParwms.put("Code", wWMSStockAlarm.Code);

            wSQLText = this.DMLChange(wSQLText);
            List<Map<String, Object>> wQueryResultList = super.queryForList(wSQLText, wParwms);
            for (Map<String, Object> wSqlDataReader : wQueryResultList) {
                wStockAlarm.ID = StringUtils.parseInt(wSqlDataReader.get("ID"));
                wStockAlarm.MaterialID = StringUtils.parseInt(wSqlDataReader.get("MaterialID"));
                wStockAlarm.Code = StringUtils.parseString(wSqlDataReader.get("Code"));
                wStockAlarm.StoreID = StringUtils.parseInt(wSqlDataReader.get("StoreID"));

                wStockAlarm.CreatorID = StringUtils.parseInt(wSqlDataReader.get("CreatorID"));
                wStockAlarm.CreateTime = StringUtils.parseCalendar(wSqlDataReader.get("CreateTime"));
                wStockAlarm.EditorID = StringUtils.parseInt(wSqlDataReader.get("EditorID"));
                wStockAlarm.EditTime = StringUtils.parseCalendar(wSqlDataReader.get("EditTime"));
                wStockAlarm.Active = StringUtils.parseInt(wSqlDataReader.get("Active"));

            }

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("WMS_CheckStockAlarm", ex);
        }
        return wStockAlarm;
    }


    private void WMS_StockAutoStockAlarm(BMSEmployee wLoginUser, WMSStockSafe wWMSStockSafe, WMSStock wWMSStock,
                                         OutResult<Integer> wErrorCode) {

        wErrorCode.set(0);
        if (wWMSStockSafe == null || wWMSStockSafe.ID <= 0 || wWMSStockSafe.Active != 1) {
            return;
        }

        double wStockMaterialNum = 0;

        if (wWMSStock != null && wWMSStock.MaterialID > 0) {
            wStockMaterialNum = wWMSStock.MaterialNum;
        }

        if ((wStockMaterialNum <= wWMSStockSafe.SafeNum && wWMSStockSafe.SafeNum > 0)
                || (wStockMaterialNum <= wWMSStockSafe.MinNum && wWMSStockSafe.MinNum > 0)
                || (wStockMaterialNum >= wWMSStockSafe.MaxNum && wWMSStockSafe.MaxNum > 0)) {
            WMSStockAlarm wWMSStockAlarm = new WMSStockAlarm();

            wWMSStockAlarm.Code = "";
            wWMSStockAlarm.StoreID = wWMSStockSafe.StoreID;
            wWMSStockAlarm.StoreName = wWMSStockSafe.StoreName;
            wWMSStockAlarm.StoreCode = wWMSStockSafe.StoreCode;
            wWMSStockAlarm.MaterialID = wWMSStockSafe.MaterialID;
            wWMSStockAlarm.MaterialCode = wWMSStockSafe.MaterialCode;
            wWMSStockAlarm.MaterialName = wWMSStockSafe.MaterialName;
            wWMSStockAlarm.StoreAreaID = wWMSStockSafe.StoreAreaID;
            wWMSStockAlarm.StoreAreaName = wWMSStockSafe.StoreAreaName;
            wWMSStockAlarm.StoreAreaCode = wWMSStockSafe.StoreAreaCode;
            wWMSStockAlarm.AlarmNum = wStockMaterialNum;
            wWMSStockAlarm.MinNum = wWMSStockSafe.MinNum;
            wWMSStockAlarm.MaxNum = wWMSStockSafe.MaxNum;
            wWMSStockAlarm.SafeNum = wWMSStockSafe.SafeNum;
            wWMSStockAlarm.UnitID = wWMSStock.UnitID;
            wWMSStockAlarm.UnitText = wWMSStock.UnitText;
            if ((wStockMaterialNum <= wWMSStockSafe.MinNum && wWMSStockSafe.MinNum > 0)
                    || (wStockMaterialNum >= wWMSStockSafe.MaxNum && wWMSStockSafe.MaxNum > 0)) {

                wWMSStockAlarm.Type = WMSStockAlarmType.LimitStock.getValue();

                this.WMS_UpdateStockAlarm(wLoginUser, wWMSStockAlarm, wErrorCode);

            }

            if ((wStockMaterialNum <= wWMSStockSafe.SafeNum && wWMSStockSafe.SafeNum > 0)
                    && (wStockMaterialNum > wWMSStockSafe.MinNum && wWMSStockSafe.MinNum > 0)) {
                wWMSStockAlarm.ID = 0;
                wWMSStockAlarm.Description = "";
                wWMSStockAlarm.Type = WMSStockAlarmType.SafeStock.getValue();

                this.WMS_UpdateStockAlarm(wLoginUser, wWMSStockAlarm, wErrorCode);

            }
        }


    }

    /**
     * 判定安全库存  库存变更一次提醒一次
     *
     * @param wLoginUser
     * @param wMaterialID
     * @param wStoreID
     * @param wStoreAreaID
     */
    @Async
    public void WMS_StockAutoStockAlarm(BMSEmployee wLoginUser, int wMaterialID, int wStoreID, int wStoreRegionID, int wStoreAreaID) {

        try {
            if (wStoreID <= 0) {
                return;
            }
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);

            WMSStockSafe wWMSStockSafe = WMSStockSafeDAO.getInstance().WMS_QueryStockSafe(wLoginUser, wMaterialID, "",
                                                                                          wStoreID, wStoreAreaID,
                                                                                          wErrorCode);

            if (wErrorCode.Result != 0) {
                logger.error("WMS_StockAutoAlarm error:{0}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }

            WMSStock wWMSStock;
            if (wWMSStockSafe != null && wWMSStockSafe.ID > 0 && wWMSStockSafe.Active == 1) {
                wWMSStock =
                        WMSStockRecordDAO.getInstance().WMS_QueryStock(wLoginUser, wStoreID, wStoreRegionID, wStoreAreaID,
                                -1, -1, wMaterialID, -1, "","", -1, -1, -1, -1, wErrorCode);

                if (wErrorCode.Result != 0) {
                    logger.error("WMS_StockAutoAlarm error:{0}",
                                 ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                    return;
                }

                this.WMS_StockAutoStockAlarm(wLoginUser, wWMSStockSafe, wWMSStock, wErrorCode);

                if (wErrorCode.Result != 0) {
                    logger.error("WMS_StockAutoAlarm error:{0}",
                                 ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                    return;
                }
            }

            wWMSStockSafe = WMSStockSafeDAO.getInstance().WMS_QueryStockSafe(wLoginUser, wMaterialID, "", wStoreID, 0,
                                                                             wErrorCode);

            if (wErrorCode.Result != 0) {
                logger.error("WMS_StockAutoAlarm error:{0}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }
            if (wWMSStockSafe != null && wWMSStockSafe.ID > 0 && wWMSStockSafe.Active == 1) {

                wWMSStock =
                        WMSStockRecordDAO.getInstance().WMS_QueryStock(wLoginUser, wStoreID, wStoreRegionID, wStoreAreaID,
                                -1, -1, wMaterialID, -1, "", "",-1, -1, -1, -1, wErrorCode);

                if (wErrorCode.Result != 0) {
                    logger.error("WMS_StockAutoAlarm error:{0}",
                                 ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                    return;
                }
                this.WMS_StockAutoStockAlarm(wLoginUser, wWMSStockSafe, wWMSStock, wErrorCode);

                if (wErrorCode.Result != 0) {
                    logger.error("WMS_StockAutoAlarm error:{0}",
                                 ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                    return;
                }
            }

        } catch (Exception ex) {
            logger.error("WMS_StockAutoAlarm", ex);
        }
    }


    public void WMS_StockThread(BMSEmployee wLoginUser) {
        int wHOUR_OF_DAY = 0;
        int wRunTimes = 0;
        while (AlarmEnable) {
            try {
                Thread.sleep(30000);
                wHOUR_OF_DAY = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
                if (wHOUR_OF_DAY > 2) {
                    wRunTimes = 0;
                    return;
                }
                if (wRunTimes > 0) {
                    return;
                }
                wRunTimes++;


                this.WMS_StockAutoDateAlarm(wLoginUser);

            } catch (Exception ex) {
                logger.error("WMS_StockAutoDateAlarm", ex);
            }
        }
    }

    /**
     * 判定库存超期  每天执行一次
     */
    public void WMS_StockAutoDateAlarm(BMSEmployee wLoginUser) {

        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);

            Map<String,Object> wParams = new HashMap<>();
            wParams.put("MaterialMarginNum", 0);
             //直接获取所有库存大于0的批次物料
            List<WMSStockRecord> wWMSStockList = WMSStockRecordDAO.getInstance().SelectPOList(wLoginUser, wParams,Pagination.getNewMaxSize(), wErrorCode);

            if (wErrorCode.Result != 0) {
                logger.error("WMS_StockAutoDateAlarm", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }

            if (wWMSStockList == null || wWMSStockList.size() <= 0) {
                return;
            }


            //获取所有安全库存
            List<WMSStockSafe> wWMSStockSafeList =
                    WMSStockSafeDAO.getInstance().WMS_QueryStockSafeList(wLoginUser, -1, -1,
                                                                         -1, "", "", -1, "", "", -1, "",
                                                                         "", "", 1, Pagination.getMaxSize(),
                                                                         wErrorCode);

            if (wErrorCode.Result != 0) {
                logger.error("WMS_StockAutoDateAlarm", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }
            if (wWMSStockSafeList == null || wWMSStockSafeList.size() <= 0) {
                return;
            }
            wWMSStockSafeList.removeIf(
                    p -> p == null || p.ID <= 0 || p.Active != 1 || (p.SafeDate <= 0 && p.SafeAlarmDate <= 0 && p.DeadDate <= 0 && p.MaxDeadDate <= 0));

            if (wWMSStockSafeList.size() <= 0) {
                return;
            }
            wWMSStockSafeList.sort((o1, o2) -> o2.StoreAreaID - o1.StoreAreaID);

            //循环判断所有库存是否超期
            for (WMSStockRecord wmsStock : wWMSStockList) {
                if (wmsStock == null || wmsStock.MaterialID <= 0 || wmsStock.MaterialNum <= 0) {
                    continue;
                }
                for (WMSStockSafe wmsStockSafe : wWMSStockSafeList) {
                    if (wmsStockSafe.StoreID != wmsStock.StoreID) {
                        continue;
                    }
                    if (wmsStockSafe.StoreAreaID > 0 && wmsStockSafe.StoreAreaID != wmsStock.StoreAreaID) {
                        continue;
                    }

                    this.WMS_StockAutoDateAlarm(wLoginUser, wmsStock, wmsStockSafe, wErrorCode);

                    break;
                }
            }

        } catch (Exception ex) {
            logger.error("WMS_StockAutoAlarm", ex);
        }
    }

    private void WMS_StockAutoDateAlarm(BMSEmployee wLoginUser, WMSStockRecord wmsStock, WMSStockSafe wWMSStockSafe,
                                        OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        try {

            if (wWMSStockSafe == null || wWMSStockSafe.ID <= 0 || wWMSStockSafe.Active != 1 || wmsStock == null || wmsStock.MaterialID < 0) {
                return;
            }


            WMSStockAlarm wWMSStockAlarm = new WMSStockAlarm();

            wWMSStockAlarm.Code = "";
            wWMSStockAlarm.StoreID = wWMSStockSafe.StoreID;
            wWMSStockAlarm.StoreName = wWMSStockSafe.StoreName;
            wWMSStockAlarm.StoreCode = wWMSStockSafe.StoreCode;
            wWMSStockAlarm.MaterialID = wWMSStockSafe.MaterialID;
            wWMSStockAlarm.MaterialCode = wWMSStockSafe.MaterialCode;
            wWMSStockAlarm.MaterialName = wWMSStockSafe.MaterialName;
            wWMSStockAlarm.StoreAreaID = wWMSStockSafe.StoreAreaID;
            wWMSStockAlarm.StoreAreaName = wWMSStockSafe.StoreAreaName;
            wWMSStockAlarm.StoreAreaCode = wWMSStockSafe.StoreAreaCode;
            wWMSStockAlarm.BatchNo = wmsStock.BatchRecordCode;
            wWMSStockAlarm.ProductDate = wmsStock.ProductDate;
            wWMSStockAlarm.StockDate = wmsStock.StockDate;
            wWMSStockAlarm.AlarmNum = wmsStock.MaterialNum;
            wWMSStockAlarm.MinNum = wWMSStockSafe.MinNum;
            wWMSStockAlarm.MaxNum = wWMSStockSafe.MaxNum;
            wWMSStockAlarm.SafeNum = wWMSStockSafe.SafeNum;
            wWMSStockAlarm.SafeDate = wWMSStockSafe.SafeDate;
            wWMSStockAlarm.MaxDeadDate = wWMSStockSafe.MaxDeadDate;
            wWMSStockAlarm.DeadDate = wWMSStockSafe.DeadDate;
            wWMSStockAlarm.SafeAlarmDate = wWMSStockSafe.SafeAlarmDate;


            Calendar wNow = Calendar.getInstance();
            int wSubDate = CalendarTool.SubDate(wNow, wWMSStockAlarm.ProductDate);
            if ((wWMSStockAlarm.SafeDate > 0 && wSubDate >= wWMSStockAlarm.SafeDate)
                    || (wWMSStockAlarm.SafeAlarmDate > 0 && wSubDate >= wWMSStockAlarm.SafeAlarmDate)) {
                wWMSStockAlarm.Type = WMSStockAlarmType.SafeDate.getValue();
                this.WMS_UpdateStockAlarm(wLoginUser, wWMSStockAlarm, wErrorCode);
            }
            wSubDate = CalendarTool.SubDate(wNow, wWMSStockAlarm.StockDate);

            if (wWMSStockAlarm.MaxDeadDate > 0 && wSubDate >= wWMSStockAlarm.MaxDeadDate) {
                wWMSStockAlarm.ID = 0;
                wWMSStockAlarm.Description = "";
                wWMSStockAlarm.Type = WMSStockAlarmType.MaxDeadDate.getValue();

                this.WMS_UpdateStockAlarm(wLoginUser, wWMSStockAlarm, wErrorCode);
            } else if (wWMSStockAlarm.DeadDate > 0 && wSubDate >= wWMSStockAlarm.DeadDate) {
                wWMSStockAlarm.ID = 0;
                wWMSStockAlarm.Description = "";
                wWMSStockAlarm.Type = WMSStockAlarmType.DeadDate.getValue();

                this.WMS_UpdateStockAlarm(wLoginUser, wWMSStockAlarm, wErrorCode);
            }


        } catch (Exception ex) {
            logger.error("WMS_StockAutoAlarm", ex);
        }
    }


    @Override
    public void destroy() throws Exception {
        AlarmEnable = false;

    }
}
